import { handler } from "./Utils";

/**
 * @Author: 陈瑞鹏
 * @Date:   2022-11-01 18:50:37
 * @Last Modified by:   陈瑞鹏
 * @Last Modified time: 2022-11-01 19:15:53
 */
export default class HttpTools {

  private static _ins: HttpTools = null;

  public static get ins(): HttpTools {
    if (this._ins == null) {
      this._ins = new HttpTools();
    }
    return this._ins;
  }

  /**
 * get 请求
 * @param url 
 * @param headers 
 * @param params 
 * @param cb 
 */
  doGet(url: string, headers: any, params: any, cb: handler, errcb: any = null) {

    if (params) {

      if (url.indexOf("?") == -1) {

        url += "?";
      }

      url += this.getQueryString(params);
    }

    this.doHttp(url, headers, null, "GET", cb);
  }

  /**
   * POST
   * @param url 
   * @param headers 
   * @param params 
   * @param cb 
   */
  doPost(url: string, headers: any, params: any, cb: handler, errcb: any = null,) {

    this.doHttp(url, headers, params, "POST", cb, errcb);
  }

  /**
   * 执行http
   * @param url 
   * @param headers 
   * @param params 
   * @param method 
   * @param cb 
   */
  doHttp(url: string, headers: any, params: any, method: string, cb: handler, errcb = null) {
    const xhr = new XMLHttpRequest();

    xhr.responseType = "text";

    xhr.onreadystatechange = this.onReadyStateChange.bind(this, xhr, cb, url);

    xhr.ontimeout = this.onTimeout.bind(this, xhr, url, errcb);

    xhr.onabort = this.onAbort.bind(this, xhr, url);

    xhr.onerror = this.onError.bind(this, xhr, url, errcb);

    xhr.open(method, url, true);

    let nowTime = new Date().getTime();
    // console.log(GameManager.ins().authorization)
    // console.log(hex_md5(GameManager.ins().authorization + "tests" + nowTime), nowTime);
    this.setHttpHeaders(xhr, {
      "Content-Type": headers['Content-Type'],
      "authorization": "",
      "timestamp": nowTime,
      "sign": ""
    })

    // if (headers) {

    //   this.setHttpHeaders(xhr, headers);
    // }

    if (cc.sys.isNative) {

      this.setHttpHeaders(xhr, { "Accept-Encoding": "gzip,deflate" });
    }

    if (params && typeof params == "object") {

      params = JSON.stringify(params);
    }

    xhr.send(params);
  }

  /**
   * 请求状态
   * @param xhr 
   * @param cb 
   */
  private onReadyStateChange(xhr: XMLHttpRequest, cb: handler, url) {

    if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) {

      let data: any;

      const response = JSON.parse(xhr.responseText);

      if (response && response.code) {

        data = response;
      } else {

        data = response;
      }

      this.notifyCallBack(cb, response.code, data);

      this.removeXhrEvent(xhr, url);
    }

    if (xhr.readyState === 4 && xhr.status == 404) {

      if (JSON.parse(xhr.responseText) && JSON.parse(xhr.responseText).msg) {

      }
    }
  }

  /**
   * 请求超时触发
   * @param xhr 
   * @param url 
   */
  private onTimeout(xhr: XMLHttpRequest, url: string, errcb = null) {

    if (errcb) {

      errcb();
    }
    this.removeXhrEvent(xhr, url);
  }

  /**
   * 用户中止加载 或 元素时触发
   * @param xhr 
   * @param url 
   */
  private onAbort(xhr: XMLHttpRequest, url: string) {

    this.removeXhrEvent(xhr, url);
  }
  /**
   * 监听错误
   * @param xhr 
   * @param url 
   */
  private onError(xhr: XMLHttpRequest, url: string, errcb = null) {

    this.removeXhrEvent(xhr, url);

    if (errcb) {

      errcb();
    }
  }

  /**
   * 清除xhr事件
   * @param xhr 
   */
  private removeXhrEvent(xhr: XMLHttpRequest, url: string) {

    xhr.ontimeout = null;

    xhr.onerror = null;

    xhr.onabort = null;

    xhr.onreadystatechange = null;
  }

  /**
   * 通知回调
   * @param cb 
   * @param code 
   * @param data 
   */
  private notifyCallBack(cb: handler, code: number, obj?: any) {

    if (cb) {
      cb.exec(code, obj);

    }
  }

  /**
   * 设置请求头
   * 例 setRequestHeader("Content-Type","application/x-www-form-urlencoded");
   * application/x-www-form-urlencoded
   * multipart/form-data
   * application/json
   * application/xml 和 text/xml
   * @param xhr 
   * @param headers 
   */
  private setHttpHeaders(xhr: XMLHttpRequest, headers: any) {

    for (let key in headers) {

      xhr.setRequestHeader(key, headers[key]);
    }
  }
  /**
 * 将数组转换
 * @param params 
 */
  private getQueryString(params: any) {

    const tmps: string[] = [];

    for (let key in params) {

      tmps.push(`${key}=${params[key]}`);
    }

    return tmps.join("&");
  }
}